package com.swordxu.yim.android.imlib.network.socket;

//import com.mogujie.tt.conn.ReconnectManager;

import android.os.Handler;

import com.swordxu.yim.android.imlib.network.packet.base.Packet;
import com.swordxu.yim.android.log.Logger;
import com.swordxu.yim.android.util.StringUtil;

import java.net.InetSocketAddress;

import javax.net.ssl.SSLException;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

public class SocketThread extends Thread {

    private Bootstrap clientBootstrap = null;

    private EventLoopGroup group;

    private ChannelFuture channelFuture = null;

    private Channel channel = null;

    public Handler subHandler = null;

    private String strHost = null;

    private int nPort = 0;

    private static Logger logger = Logger.getLogger(SocketThread.class);

    public SocketThread(String strHost, int nPort, SimpleChannelInboundHandler handler) {

        this.strHost = strHost;

        this.nPort = nPort;

        try {
            init(handler);
        } catch (SSLException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void run() {
        doConnect();
    }

    private void init(final SimpleChannelInboundHandler handler) throws SSLException {
        group = new NioEventLoopGroup();
        clientBootstrap = new Bootstrap();

        clientBootstrap.channel(NioSocketChannel.class);
//        final SslContext sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
        clientBootstrap.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            public void initChannel(SocketChannel ch) throws Exception {
                ChannelPipeline p = ch.pipeline();
                p.addLast(new StringDecoder());
                p.addLast(new StringEncoder());
                p.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4));
                p.addLast("frameEncoder", new LengthFieldPrepender(4));
//                p.addLast("encoder", new LengthFieldPrepender(4, false));
                //p.addLast(new LoggingHandler(LogLevel.INFO));
                p.addLast(handler);
            }
        });

//        clientBootstrap.option(ChannelOption.TCP_NODELAY, true);
        clientBootstrap.option(ChannelOption.SO_KEEPALIVE, true);
        clientBootstrap.group(group);
    }

    public boolean doConnect() {
        try {
            if ((null == channel || (null != channel && !channel.isActive()))) {
                channelFuture = clientBootstrap.connect(new InetSocketAddress(
                        strHost, nPort));
                channel = channelFuture.sync().channel();
                if (!channelFuture.isSuccess()) {
                    channelFuture.cause().printStackTrace();
                    group.shutdownGracefully();
                    return false;
                }
            }
//            channelFuture.channel().closeFuture().awaitUninterruptibly();
//            group.shutdownGracefully();
            return true;

        } catch (Exception e) {
            logger.e("do connect failed. e: %s", e.getMessage());
            e.printStackTrace();
            return false;

        } finally {
//            group.shutdownGracefully();
        }

    }

    public Channel getChannel() {
        return channel;
    }

    public void close() {

        if (null == channelFuture)

            return;

//        if (null != channelFuture.getChannel()) {
//
//            channelFuture.getChannel().close();
//
//        }
//
//        channelFuture.cancel();

    }

    public boolean sendPacket(String p) {
        if (!StringUtil.isEmpty(p) && null != channelFuture.channel()) {
            channel.write(p);
            logger.d("packet#send ok");
            return true;

        } else {

            logger.e("packet#send failed");
            return false;

        }
    }

    public boolean sendPacket(Packet p) {
        if (null != p && null != channelFuture.channel()) {

            channelFuture.channel().writeAndFlush(p.encode());
            System.out.println("请求msgserver ip 消息发送.");
            logger.d("packet#send ok");
            return true;

        } else {

            logger.e("packet#send failed");
            return false;

        }

    }
}

